package com.nys.conci.base.utilitario;

import com.nys.conci.base.excepcion.ExcepcionServicio;
import com.nys.conci.base.utilitario.logger.LoggerUtil;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Clase encargada de contener varios metodos utilitarios de fechas, que pueden
 * utilizarse en la aplicacion.
 *
 * @author Adam M. Gamboa Gonzalez
 */
public class FechaUtil {
    public static final SimpleDateFormat formatoDia = new SimpleDateFormat("dd/MM/yyyy");
    public static final SimpleDateFormat formatoHora = new SimpleDateFormat("h:mm a");
    public static final DateFormat formatoDiaHora = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
        /**
     * Devuelve la fecha actual del sistema.
     * @return java.util.Date con la fecha actual
     * @since 17/08/2009
     */
    public static Date getFechaActual() {
        return GregorianCalendar.getInstance(new Locale("es", "CR")).getTime();
    } 
    
    public static Date getFechaHoraActual() throws ParseException{  
        String cadenaFecha = formatoDiaHora.format(new Date());
        return formatoDiaHora.parse(cadenaFecha);  
    }
    
    public static Date getFechaActualSinHora() throws ParseException{  
        String cadenaFecha = formatoDia.format(new Date());
        return formatoDia.parse(cadenaFecha);  
    }

    /**
     * Metodo encargado de retornar la fecha actual del servidor
     *
     * @return Fecha actual
     */
    public static Date obtenerFechaActual() {
        return Calendar.getInstance().getTime();
    }

    /**
     * Deja el tiempo en cero, retorna solo la fecha
     *
     * @param fechaToTrunc Fecha a truncar
     * @return Fecha truncada
     */
    public static Date truncFecha(Date fechaToTrunc) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(fechaToTrunc);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }
    
        /**
     * Metodo encargado de devolverme el nombre de un mes. El mes es indicado
     * por un numero de 1 a 12 respectivo a mes a buscar nombre. Si no encuentra
     * el mes retorna un
     * <code>""</code>.
     *
     * @param id_mes Numero del mes a obtener nombre
     * @return Nombre del mes obtenido
     */
    public static String obtenerNombreMes(int id_mes) {
        if (id_mes == 1) {
            return "Enero";
        }
        if (id_mes == 2) {
            return "Febrero";
        }
        if (id_mes == 3) {
            return "Marzo";
        }
        if (id_mes == 4) {
            return "Abril";
        }
        if (id_mes == 5) {
            return "Mayo";
        }
        if (id_mes == 6) {
            return "Junio";
        }
        if (id_mes == 7) {
            return "Julio";
        }
        if (id_mes == 8) {
            return "Agosto";
        }
        if (id_mes == 9) {
            return "Setiembre";
        }
        if (id_mes == 10) {
            return "Octubre";
        }
        if (id_mes == 11) {
            return "Noviembre";
        }
        if (id_mes == 12) {
            return "Diciembre";
        }
        return "";
    }

    /**
     * MÃ©todo que retorna la cantidad de dÃ­as que hay entre dos fechas
     *
     * @param a la primer fecha a evaluar
     * @param b la segunda fecha a evaluar
     * @return int con el resultado de la operaciÃ³n
     */
    public static int obtenerDiasEntreFechas(Date a, Date b) {
        int diferencia_temp = 0;
        int diferencia = 0;

        Calendar menor = Calendar.getInstance();
        Calendar mayor = Calendar.getInstance();


        if (a.compareTo(b) < 0) {
            menor.setTime(a);
            mayor.setTime(b);
        } else {
            menor.setTime(b);
            mayor.setTime(a);
        }


        while (menor.get(Calendar.YEAR) != menor.get(Calendar.YEAR)) {
            diferencia_temp = 365 * (mayor.get(Calendar.YEAR) - menor.get(Calendar.YEAR));
            diferencia += diferencia_temp;
            menor.add(Calendar.DAY_OF_YEAR, diferencia_temp);
        }


        if (menor.get(Calendar.DAY_OF_YEAR) != mayor.get(Calendar.DAY_OF_YEAR)) {
            diferencia_temp = mayor.get(Calendar.DAY_OF_YEAR) - menor.get(Calendar.DAY_OF_YEAR);
            diferencia += diferencia_temp;
            menor.add(Calendar.DAY_OF_YEAR, diferencia_temp);
        }
        return diferencia;
    }

    /**
     * Metodo encargado de indicarme si el parametro fecha_comparar, esta dentro
     * del rango de fechas comprendido entre fecha_inicio y fecha_fin. El rango
     * es inclusivo, es decir si la fecha_comparar es igual, fecha_inicio o
     * fecha_fin, entonces se dice que aun esta dentro del rango.
     * @param fecha_comparar Date
     * @param fecha_inicio Date
     * @param fecha_fin Date
     * @return  boolean
     */
    public static boolean esEnRangoEstrictoFechas(Date fecha_comparar, Date fecha_inicio, Date fecha_fin) {
        if (fecha_inicio == null || fecha_fin == null) {
            return false;
        }
        return ((!fecha_comparar.before(fecha_inicio))
                && (!fecha_fin.before(fecha_comparar)));
    }

    /**
     * Metodo encargado de comparar fechas, recibe la fecha 1 separado en 2
     * parametros Date (las fecha y la hora), y recibe la fecha 2 separado en 2
     * parametros (fecha2, hora2).
     *
     * @param fecha1 Dias de la fecha 1
     * @param hora1 Horas de la fecha 1
     * @param fecha2 Dias de la fecha 2
     * @param hora2 Horas de la fecha 2
     *
     * @return El valor 0 si ambas fechas son iguales. Un valor menos a 0, si la
     * fecha1 es menor a la fecha 2. Un valor valor mayor a 0 si la fecha 1 es
     * mayor que la fecha 2.
     */
    public static int compararFechas(Date fecha1, Date hora1, Date fecha2, Date hora2) {
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        Calendar h1 = Calendar.getInstance();
        Calendar h2 = Calendar.getInstance();

        c1.setTime(fecha1);
        c2.setTime(fecha2);
        h1.setTime(hora1);
        h2.setTime(hora2);

        c1.set(Calendar.HOUR_OF_DAY, h1.get(Calendar.HOUR_OF_DAY));
        c1.set(Calendar.MINUTE, h1.get(Calendar.MINUTE));
        c1.set(Calendar.SECOND, h1.get(Calendar.SECOND));

        c2.set(Calendar.HOUR_OF_DAY, h2.get(Calendar.HOUR_OF_DAY));
        c2.set(Calendar.MINUTE, h2.get(Calendar.MINUTE));
        c2.set(Calendar.SECOND, h2.get(Calendar.SECOND));

        return c1.compareTo(c2);
    }

    /**
     * Metodo encargado del calculo, para saber si dada una fecha de nacimiento,
     * una persona es mayor de edad a la fecha actual. Se toma como 18, la
     * mayoria de edad.
     *
     * @param fecha_nacimiento Fecha de nacimiento de la persona.
     * @return True si es mayor de edad, false si no lo es.
     */
    public static boolean esMayorEdad(Date fecha_nacimiento) {
        if (fecha_nacimiento != null) {
            Calendar nacimiento = Calendar.getInstance();
            nacimiento.setTime(fecha_nacimiento);
            Calendar actual = Calendar.getInstance();
            nacimiento.add(Calendar.YEAR, 18);

            if (nacimiento.before(actual)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Metodo encargado de obtener y regresar el anno de la fecha actual del
     * sistema.
     *
     * @return Anno actual
     */
    public static Integer obtenerAnnoActual() {
        Calendar c = Calendar.getInstance();
        return c.get(Calendar.YEAR);
    }

    /**
     * Obtiene un String en formato hh:mm:ss con la hora actual del sistema.
     *
     * @return Hora actual del sistema.
     */
    public static String obtenerHoraActual() {
        Calendar c = Calendar.getInstance();
        return c.get(Calendar.HOUR_OF_DAY) + ":" + c.get(Calendar.MINUTE) + ":" + c.get(Calendar.SECOND);
    }

    

    /**
     * Metodo encargado de obtener el dia del mes, de la fecha recibida como
     * parametro.
     *
     * @param fecha Fecha a la cual se desea obtener el dia del mes.
     * @return Dia del mes
     */
    public static int obtenerDiaDelMes(Date fecha) {
        Calendar c = Calendar.getInstance();
        c.setTime(fecha);
        return c.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * Metodo encargado de obtener el Mes de una fecha. El mes lo retorna como
     * un numero indicando el numero del mes. Los valores retornados van de 1
     * hasta 12, donde cada numero es el respectivo mes.
     *
     * @param fecha Fecha a obtener el mes.
     * @return Mes de la fecha
     */
    public static int obtenerMesDelAnno(Date fecha) {
        Calendar c = Calendar.getInstance();
        c.setTime(fecha);
        return c.get(Calendar.MONTH) + 1;
    }


    /**
     * Metodo encargado de obtener el año de un objeto Date, con una fecha
     * especifica.
     *
     * @param fecha Fecha a obtener año.
     * @return Año de la fecha
     */
    public static int obtenerAnno(Date fecha) {
        Calendar c = Calendar.getInstance();
        c.setTime(fecha);
        return c.get(Calendar.YEAR);
    }

    /**
     * Metodo encargado de retornar la fecha actual de la base de datos
     *
     * @return Fecha actual de la base de datos
     */
    //TODO Este metodo hay que modificarlo, para que realice la conexion con la base de datos, y 
    // obtenga el SYSDATE, por mientras devuelve por defecto la hora de la aplicacion
    public static Date obtenerFechaActualDB() {

        return Calendar.getInstance().getTime();
    }

    /**
     * Devuelve la hora de la base de datos
     *
     * @return int con la hora en formato hh24
     */
    public static int obtenerHoraDB() {
        return Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
    }

    /**
     * Devuelve los minutos de la base de datos
     *
     * @return int con los minutos
     */
    public static int obtenerMinutosDB() {
        return Calendar.getInstance().get(Calendar.MINUTE);
    }

    /**
     * Formatea un Date a un String con el formato especifico. ejemplo de un
     * Date a un -> "10-09-2010""
     *
     * @param fecha java.util.Date
     * @param formato String
     * @return fechaNueva String
     * @author wPorras
     * @since 2011/08/30
     */
    public static String convertirFecha(java.util.Date fecha, String formato) {
        Locale cr = new Locale("es", "CR");
        SimpleDateFormat formatoSdf = new SimpleDateFormat(formato, cr);
        String fechaNueva = formatoSdf.format(fecha);
        return fechaNueva;
    }//convertirFecha

    /**
     * Formatea un String con un formato especifico a un java.util.Date
     *
     * @param fechaActual
     * @param formato
     * @author wPorras
     * @since 2011/08/30
     * @return fechaNueva Date
     */
    public static Date convertirFecha(String fechaActual, String formato) {
        SimpleDateFormat formatoSdf = new SimpleDateFormat(formato);
        Date fechaNueva = null;
        try {
            fechaNueva = formatoSdf.parse(fechaActual);
        } catch (ParseException ex) {
            LoggerUtil.registrarLogError(ex, false);
            throw new ExcepcionServicio(" Error al formatear la fecha", "", ex, FechaUtil.class);

        }
        return fechaNueva;
    }//convertirFecha

    /**
     * Formatea un String con un formato especifico a un nuevo String con un
     * formato especifico ejemplo ("10-09-2010" "dd-MM-yyyy") -> ("2010/09/10"
     * "yyyy/MM/dd")
     *
     * @param fechaActual String
     * @param formatoActual String
     * @param formatoDestino String
     * @return fechaNuevo - String
     * @author wPorras
     * @since 2011/08/30
     */
    public static String formatearFecha(String fechaActual, String formatoActual, String formatoDestino) {
        Date fechaActualD = convertirFecha(fechaActual, formatoActual);
        String fechaNueva = convertirFecha(fechaActualD, formatoDestino);
        return fechaNueva;
    }//formatearFecha
}
